import React, {
    PureComponent
} from 'react';

import {
    View,
    StyleSheet
} from 'react-native';

import {
    FromUser,
    MessageItem
} from './types';

import moment from 'moment';

import MessageView from './message';

import InputView from './inputView';

const _copy = (data: any) => (
    JSON.parse(JSON.stringify(data))
)

interface _Props {
    author: any,
    chatRoomId: string,
    onLoadHistory: Function,
    onLoadBottom: Function,
    onSendMessage: Function,
    initialMessages: Array<MessageItem>
}

interface State {
    stateList?: Array<MessageItem>
}

class ImUi extends PureComponent<_Props, State> {
    static defaultProps = {
        author: {},
        chatRoomId: ``,
        initialMessages: [],
        onLoadBottom: () => null,
        onLoadHistory: () => null,
        onSendMessage: () => null
    }

    constructor(props: _Props) {
        super(props);
        const {
            initialMessages
        } = props;
        this.state = {
            stateList: _copy(initialMessages)
        }
    }

    private scroll: any = null;

    get author() {
        const {
            author
        } = this.props;
        return author;
    }

    get userId() {
        const {
            userId = 0
        } = this.author;
        return userId;
    }

    get chatRoomId() {
        const {
            chatRoomId
        } = this.props;
        return chatRoomId;
    }

    get avatar() {
        const {
            photos = []
        } = this.author;
        const {
            url
        } = photos.find((item: any) => (
            !!item.isAvatar
        )) || {}
        return url;
    }

    get fromUser(): FromUser {
        const {
            userId,
            nickName
        } = this.author;
        return {
            userId: userId,
            avatarPath: this.avatar,
            displayName: nickName,
        }
    }

    private _createMsg(text: string = ``) {
        const _timeString = (
            this._timeString()
        )
        return {
            text: text,
            extend: ``,
            duration: 0,
            targetId: ``,
            mediaPath: ``,
            msgType: `text`,
            chatHistoryId: ``,
            isOutgoing: true,
            status: `send_going`,
            sentTime:_timeString,
            fromUser: this.fromUser,
            chatRoomId: this.chatRoomId,
            msgId: `${Date.now()}${this.userId}`
        } as MessageItem | any;
    }

    private _timeString = (time?: any) => {
        const date = !!time ? new Date(time) : new Date();
        return Math.floor(date.getTime()/1000);
    }

    getSnapshotBeforeUpdate(
        prevProps: _Props,
        prevState: State
    ) {
        const {
            stateList=[]
        } = prevState;

        const {
            initialMessages=[]
        } = this.props;

        const _hasInit = (
            !!initialMessages.length
        )
        return (
            !stateList.length && _hasInit
        )
    }

    componentDidUpdate(a:any, b:any, pass:boolean) {
        const {
            onLoadBottom
        } = this.props;
        if (pass) {
            onLoadBottom(
                this._onLoadBottomEnd
            )
        }
    }

    componentDidMount() {
        const {
            onLoadBottom
        } = this.props;

        const {
            stateList=[]
        } = this.state;

        if (stateList.length > 0) {
            onLoadBottom(
                this._onLoadBottomEnd
            )
        }
    }

    static getDerivedStateFromProps(
        nextProps: _Props,
        prevState: State
    ) {
        const {
            stateList=[]
        } = prevState;

        const {
            initialMessages=[]
        } = nextProps;

        const _hasInit = (
            !!initialMessages.length
        )

        if (!stateList.length && _hasInit) {
            return {
                stateList: _copy(initialMessages)
            }
        }
        return prevState;
    }

    private _onLoadPage = (done: Function) => {
        const {
            onLoadHistory
        } = this.props;
        onLoadHistory((list: Array<MessageItem> = []) => (
            this._onLoadPageEnd(done, list)
        ))
    }

    private _onLoadBottomEnd = (
        list: Array<MessageItem> = []
    ) => {
        this.appendMessages(list)
    }

    private _onLoadPageEnd = (
        done: Function,
        list: Array<MessageItem> = []
    ) => {
        done();
        this.insetMessages(list);
    }

    public insetMessages = (
        list: Array<MessageItem> = []
    ) => {
        const {
            stateList
        } = this.state;

        this.setState({
            stateList: [...list, ...stateList]
        })
    }

    public appendMessages = (
        list: Array<MessageItem> = []
    ) => {
        const {
            stateList
        } = this.state;

        this.setState({
            stateList: [...stateList, ...list]
        })

        if (this.scroll) {
            this.scroll.scrollToEnd();
        }
    }

    public updateMessage = (
        item: MessageItem
    ) => {
        const {
            stateList=[]
        } = this.state;
        const {
            msgId,
            chatRoomId
        } = item;
        const _find = (item: any) => (
            (item.msgId === msgId) &&
            (item.chatRoomId === chatRoomId)
        )
        const index = (
            stateList.findIndex(_find)
        )
        if (index > -1) {
            stateList[index] = item;
            this.setState({
                stateList: [...stateList]
            })
        }
    }

    public deleteMessage = (
        item: MessageItem
    ) => new Promise(resolve => {
        const {
            stateList=[]
        } = this.state;
        const {
            msgId,
            chatRoomId
        } = item;
        const _find = (item: any) => (
            (item.msgId === msgId) &&
            (item.chatRoomId === chatRoomId)
        )
        const index = (
            stateList.findIndex(_find)
        )
        if (index > -1) {
            stateList.splice(index, 1);
            this.setState({
                stateList: [...stateList]
            }, resolve)
        }
    })

    private _onReSend = async (item: MessageItem|any) => {
        await this.deleteMessage(item)
        const _item = {
            ...item,
            isReSending: true,
            status: `send_going`
        }
        this._onSendMessage(_item);
    }

    private _onSendFile = (file:any) => {
        const _message = (
            this._createMsg(`A Image`)
        )
        _message.msgType = 'image';
        _message.mediaPath = file.path;
        this._onSendMessage(_message);
    }

    private _onSendText = (text: string) => {
        const _message = (
            this._createMsg(text)
        )
        this._onSendMessage(_message)
    }

    private _onSendMessage = (
        message: MessageItem
    ) => {
        const {
            onSendMessage
        } = this.props;
        onSendMessage(
            message,
            this._onSendBefore,
            this._onSendUpdate
        )
    }

    private _onSendBefore = (
        item: MessageItem
    ) => {
        this.appendMessages([item]);
    }

    private _onSendUpdate = (
        item: MessageItem
    ) => {
        this.updateMessage(item);
    }

    render() {

        const {
            stateList
        } = this.state;

        return (
            <View style={styles.container}>
                <MessageView
                    list={stateList}
                    userId={this.userId}
                    onReSend={this._onReSend}
                    ref={e => this.scroll = e}
                    onLoadPage={this._onLoadPage}
                />
                <InputView
                    onSendText={this._onSendText}
                    onSendFile={this._onSendFile}
                />
            </View>
        )
    }
}

export default ImUi;


const styles = StyleSheet.create({
    container: {
        flex: 1
    }
}) as any;